import re
import time
import requests
from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By
from config import Config

class DanmuFetcher:
    """弹幕获取类"""
    
    def __init__(self, driver):
        self.driver = driver
        self.session = self._create_session()
    
    def _create_session(self):
        """创建请求会话"""
        session = requests.Session()
        session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        })
        return session
    
    def get_video_cid(self, bvid):
        """获取视频CID"""
        try:
            video_url = f"https://www.bilibili.com/video/{bvid}"
            print(f"访问视频页面: {video_url}")
            
            self.driver.get(video_url)
            time.sleep(4)
            
            if not self.driver.title or "验证" in self.driver.title or "错误" in self.driver.title:
                print("页面加载异常，跳过")
                return None
            
            cid = self._get_cid_from_initial_state()
            if cid:
                return cid
            
            cid = self._get_cid_from_scripts()
            if cid:
                return cid
            
            print("无法获取CID")
            return None
            
        except Exception as e:
            print(f"获取CID异常: {e}")
            return None
    
    def _get_cid_from_initial_state(self):
        """从INITIAL_STATE获取CID"""
        try:
            initial_state_script = """
            if (window.__INITIAL_STATE__) {
                return window.__INITIAL_STATE__;
            }
            return null;
            """
            initial_state = self.driver.execute_script(initial_state_script)
            
            if initial_state and 'videoData' in initial_state:
                cid = initial_state['videoData']['cid']
                print(f"从INITIAL_STATE获取到CID: {cid}")
                return cid
        except Exception as e:
            print(f"从INITIAL_STATE获取CID失败: {e}")
        return None
    
    def _get_cid_from_scripts(self):
        """从script标签获取CID"""
        try:
            scripts = self.driver.find_elements(By.TAG_NAME, 'script')
            for script in scripts:
                script_content = script.get_attribute('innerHTML')
                if script_content and 'cid' in script_content:
                    cid_match = re.search(r'"cid":(\d+)', script_content)
                    if cid_match:
                        cid = cid_match.group(1)
                        print(f"从script标签获取到CID: {cid}")
                        return cid
        except Exception as e:
            print(f"从script标签获取CID失败: {e}")
        return None
    
    def fetch_danmu_data(self, cid, bvid):
        """获取弹幕数据"""
        try:
            self.session.headers.update({
                'Referer': f'https://www.bilibili.com/video/{bvid}',
            })
            
            danmu_url = f"https://api.bilibili.com/x/v1/dm/list.so?oid={cid}"
            print(f"请求弹幕API: {danmu_url}")
            
            response = self.session.get(danmu_url, timeout=15)
            
            if response.status_code == 200:
                content = response.text
                if content.strip().startswith('<?xml') or '<d ' in content:
                    response.encoding = 'utf-8'
                    soup = BeautifulSoup(response.text, 'lxml-xml')
                    danmus = []
                    
                    for d in soup.find_all('d'):
                        text = d.get_text()
                        if text and self.filter_danmu(text):
                            danmus.append(text)
                    
                    return danmus
                else:
                    print(f"弹幕API返回非XML内容")
            else:
                print(f"弹幕API请求失败，状态码: {response.status_code}")
            return []
        except Exception as e:
            print(f"获取弹幕失败: {e}")
            return []
    
    def filter_danmu(self, text):
        """过滤噪声弹幕"""
        if not text or len(text.strip()) <= 1:
            return False
            
        text_clean = text.strip()
        
        for pattern in Config.NOISE_PATTERNS:
            if re.match(pattern, text_clean):
                return False
        
        return True